package server.business;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import forum.server.controller.ForumFacade;
import forum.server.domain.*;
import forum.server.persistence.DataManipulatorProxy;
import forum.server.exceptions.*;

public class ForumFacadeTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}
	
	@Before
	public void setUp() throws Exception {
		DataManipulatorProxy.getInstance().resetDataBase();
	}

	@After
	public void tearDown() throws Exception {
	}
	
	

	@Test
	public void testRegister() {
		ForumFacade f = null;
		try {
			f = new ForumFacade();
			LoggedInUser u = f.register("mirskyil", "1234");
			assertEquals("mirskyil", u.getUsername());
			assertFalse(u.getUsername().equals("mirsky"));
		} catch (Exception ex) {
			fail("Unexpected exception: " + ex.getMessage());
		}
		try {
			f.register("mirskyil", "123");
			fail("Should have thrown an exception.");
		} catch (DatabaseException ex) {
			fail ("Unexpected exception: " + ex.getMessage());
		} catch (RegistrationException ex) {
			
		}
	}
	
	@Test
	public void testViewForum() {
		ForumFacade f = null;
		try {
			f = new ForumFacade();
			assertNotNull(f.viewForum());
		} catch (Exception ex) {
			fail("Unexpected exception: " + ex.getMessage());
		}
	}

	@Test
	public void testLogin() {
		ForumFacade f = null;
		LoggedInUser u;
		try {
			f = new ForumFacade();
			f.register("mirskyil", "1234");			
		} catch (Exception ex) {
			fail("Unexpected exception.");
		}
		try {
			u = f.login("tamirv", "1234");
			fail("Should have thrown an exception.");
		} catch (DatabaseException ex) {
			fail ("Unexpected exception: " + ex.getMessage());
		} catch (Exception ex) {
		
		}
		try {
			u = f.login("mirskyil", "12345");
			fail("Should have thrown an exception.");
		} catch (DatabaseException ex) {
			fail ("Unexpected exception: " + ex.getMessage());
		} catch (Exception ex) {
		
		}
		try {
			u = f.login("mirskyil", "1234");
			assertEquals(u.getUsername(), "mirskyil");
		} catch (Exception ex) {
			fail("Unexpected exception.");
		}	
	}

	@Test
	public void testLogoff() {
		ForumFacade f;
		try {
			f = new ForumFacade();
			f.register("mirskyil", "1234");
			f.logoff();
			f.addPost("test", new PostContent("shouldn't execute"));
			fail("Should have thrown an exception.");
		} catch (DatabaseException ex) {
			fail ("Unexpected exception: " + ex.getMessage());
		} catch (Exception ex) {
			
		}
	}

	@Test
	public void testAddPost() {
		ForumFacade f = null;
		try {
			f = new ForumFacade();
			f.addPost("header 1", new PostContent("content 1"));
			fail("Should have thrown an exception.");
		} catch (DatabaseException ex) {
			fail ("Unexpected exception: " + ex.getMessage());
		} catch (NotLoggedInException ex) {
			
		}
		try {
			f.register("mirskyil", "1234");
			f.login("mirskyil", "1234");
			Post tPost = f.addPost("header 1", new PostContent("content 1"));
			assertEquals(tPost.getAuthor(), "mirskyil");
			assertEquals(tPost.getHeader(), "header 1");
			assertEquals(tPost.getContent(), new PostContent("content 1"));
		} catch (Exception ex) {
			fail("Unexpected exception.");
		}
	}

	@Test
	public void testModifyPost() {
		ForumFacade f = null;
		Post p = null;
		try {
			f = new ForumFacade();
			f.register("mirskyil", "1234");
			f.login("mirskyil", "1234");
			p = f.addPost("header 2", new PostContent("content 2"));
			f.register("tamirv", "123");
			f.modifyPost(p.getPostId(), new PostContent("modified content 2"));
			fail("Should have thrown an exception.");
		} catch (UnauthorizedOpException ex) {
			
		} catch (Exception ex) {
			fail("Unexpected exception: " + ex.getMessage());
		}
		try {
			f.logoff();
			f.login("mirskyil", "1234");
			Post newPost = f.modifyPost(p.getPostId(), new PostContent("modified content 2"));
			assertEquals(newPost.getContent(), new PostContent("modified content 2"));
			assertEquals(newPost.getHeader(), "header 2");
		} catch (Exception ex) {
			fail("Unexpected exception: " + ex.getMessage());
		}
	}

	@Test
	public void testReplyToPost() {
		ForumFacade f = null;
		Post p1 = null;
		Post p2 = null;
		try {
			f = new ForumFacade();
			f.register("mirskyil", "1234");
			f.login("mirskyil", "1234");
			p1 = f.addPost("header 3", new PostContent("content 3"));
			f.register("alonf", "123");
			f.login("alonf", "123");
			p2 = f.replyToPost(p1.getPostId(), "reply", new PostContent("reply to ost 3"));
			assertEquals(p2.getParentId(), p1.getPostId());
			assertFalse(p1.isReply());
			assertTrue(p2.isReply());
		} catch (Exception ex) {
			fail("Unexpected exception: " + ex.getMessage());
		}
	}

	@Test
	public void testPromoteModerator() {
		ForumFacade f = null;
		Post p = null;
		try {
			f = new ForumFacade();
			f.register("mirskyil", "123");
			f.register("nrp", "111");
			f.login("mirskyil", "123");
			p = f.addPost("test", new PostContent("xx"));
			f.promoteModerator("mirskyil");
			fail("Should have thrown an exception.");
		} catch (UnauthorizedOpException ex) {
			
		} catch (Exception ex) {
			fail("Unexpected exception");
		}
		try {
			f.login("admin", "1234");
			f.promoteModerator("mirskyil");
			f.modifyPost(p.getPostId(), new PostContent("aaa"));
			assertEquals(DataManipulatorProxy.getInstance().getPost(p.getPostId()).getContent(),
					new PostContent("aaa"));
			f.logoff();
			f.login("mirskyil", "123");
			f.modifyPost(p.getPostId(), new PostContent("bbb"));
			assertEquals(DataManipulatorProxy.getInstance().getPost(p.getPostId()).getContent(),
					new PostContent("bbb"));
		} catch (Exception ex) {
			fail("Unexpected exception: " + ex.getMessage());
		}
	}

	@Test
	public void testDemoteModerator() {
		ForumFacade f = null;
		Post p = null;
		try {
			f = new ForumFacade();
			f.register("mirskyil", "123");
			f.register("nrp", "111");
			f.login("admin", "1234");
			p = f.addPost("test", new PostContent("xx"));
			f.promoteModerator("mirskyil");
			f.logoff();
			f.login("nrp", "111");
			f.demoteModerator("mirskyil");
			fail("Should have thrown an exception.");
		} catch (UnauthorizedOpException ex) {
			
		} catch (Exception ex) {
			fail("Unexpected exception");
		}
		try {
			f.logoff();
			f.login("admin", "1234");
			f.demoteModerator("mirskyil");
			f.login("mirskyil", "123");
			f.modifyPost(p.getPostId(), new PostContent("aaa"));
			fail("Should have thrown an exception.");
		} catch (UnauthorizedOpException ex) {
		
		} catch (Exception ex) {
			fail("Unexpected exception: " + ex.getMessage());
		}
	}
	

	@Test
	public void testSearchByAuthor() {
		ForumFacade f = null;
		try{
			f = new ForumFacade();
			f.register("mirskyil", "123");
			f.login("mirskyil", "123");
			f.addPost("Hello", new PostContent("test content"));
			assertTrue(f.searchByAuthor("mirskyil", 0, 1).length() > 0);
		}
		catch (Exception e){
			fail("Something went wrong!");
		}		
	}

	@Test
	public void testSearchByContent() {
		ForumFacade f = null;
		try{
			f = new ForumFacade();
			f.register("mirskyil", "123");
			f.login("mirskyil", "123");
			f.addPost("Hello", new PostContent("test content"));
			assertTrue(f.searchByContent("test", 0, 1).length() > 0);
		}
		catch (Exception e){
			fail("Something went wrong!");
		}	
	}

}
